import fs = require('fs');
import multer = require('multer');
import express = require('express');
import {Promise} from 'es6-promise';
import {Options, StorageEngine} from 'multer';
import {Request, Response, NextFunction} from "express";

import PWSApp from "./app";
import {Magics} from "./magics";

import {BaseAction} from "./base.action";
import DiskStorage from "./upload.storage";
import { ErrCode } from './error.code';

export default class UploadImgBase extends BaseAction {
    private _limit: Object;
    private _uploader: any;
    private _options: Options;
    private _storage: DiskStorage;

    constructor(app: PWSApp) {
        super(app);
        this._storage = new DiskStorage(Magics.ImgsPath);
        this._limit = {
            fileSize: Magics.UploadFileMaxSize,
            fieldSize: Magics.UploadFieldMaxSize
        };
        this._options = {};
        this._options.storage = <StorageEngine>this._storage;
        this._options.limits  = this._limit;
        this._options.fileFilter = this._fileFilter;
        this._uploader = multer(this._options);
    }

    name() { return `${this.app.name}UploadBase`; }

    upload(fields: Object, req: Request, res: Response) {
        return new Promise((resolve, reject) => {
            let uploader = this._uploader['fields'](fields);
            uploader(req, res, (err) => {
                if (err) {
                    reject(this.errorCode(err));
                    return;
                }
                resolve();
            });
        })
    }

    private _fileFilter(req: Request, file: any, cb: Function): void {
        let type = file['mimetype'];
        let fileTypeRex = /image\/(pjpeg|(x-|)png|jp(e|)g|gif)/;
        if(!fileTypeRex.test(type) ){
            let err = new Error("File type is not supported");
            err['code'] = "LIMIT_FILE_TYPE";
            this.logger.D(this.name(), err);
            cb(err);
            return;
        }
        cb(null, true);
    }

    private errorCode(err) {
        let code;
        switch(err.code) {
            case "LIMIT_FILE_SIZE":
                code = ErrCode.FileSizeErr;
                break;
            case "LIMIT_FILE_TYPE":
                code = ErrCode.FileTypeErr;
                break;
            case "LIMIT_UNEXPECTED_FILE":
                code = ErrCode.FileUnexpectErr;
                break;
            default:
                code = ErrCode.UnknownError;
        }
        return code;
    }
}
